package com.leyou.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.user.dto.UserDTO;
import com.leyou.user.entity.TbUser;
import com.leyou.user.mapper.TbUserMapper;
import com.leyou.user.service.TbUserService;
import org.apache.catalina.User;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.leyou.common.constants.RocketMQConstants.TAGS.VERIFY_CODE_TAGS;
import static com.leyou.common.constants.RocketMQConstants.TOPIC.SMS_TOPIC_NAME;
import static com.leyou.common.constants.SmsConstants.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author SYL
 * @since 2020-02-11
 */
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser> implements TbUserService {

    @Override
    public Boolean checkData(String data, Integer type) {

        QueryWrapper<TbUser> queryWrapper = new QueryWrapper();

        switch (type){
            case 1:{
//        type:1  查询的是用户名
                queryWrapper.lambda().eq(TbUser::getUsername,data);
                break;
            }
            case 2:{
//        type:2 查询的是手机号
                queryWrapper.lambda().eq(TbUser::getPhone,data);
                break;
            }
            default:
                throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
//        查询出来的数据没有用
//        判断是否能查出来数据，如果能查出来数据 意味着什么？ 意味着这个data数据是不能使用的 return false
//        如果有数据  return false 如果没有数据  return true
        int count = this.count(queryWrapper);
        return count==0?true:false;
    }

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void sendCode(String phone) {
//        发送验证码   1、把发送短信的任务放入到mq中
        Map map = new HashMap();
        String randomNumeric = RandomStringUtils.randomNumeric(4); //随机产生4位的数字
        map.put(SMS_PARAM_KEY_PHONE,phone);
        map.put(SMS_PARAM_KEY_SIGN_NAME,"快乐优雅购物");
        map.put(SMS_PARAM_KEY_TEMPLATE_CODE,"SMS_173479212");
        map.put(SMS_PARAM_KEY_TEMPLATE_PARAM,"{\"code\":\""+randomNumeric+"\"}");
        rocketMQTemplate.convertAndSend(SMS_TOPIC_NAME+":"+VERIFY_CODE_TAGS,map);
//                     2、把验证码放入到redis中，设置时效性 5分钟，为了测试方便我使用30秒

//        redisTemplate.boundValueOps("").set(randomNumeric,5, TimeUnit.MINUTES);
        redisTemplate.boundValueOps("ly:sms:"+phone).set(randomNumeric,30, TimeUnit.SECONDS);

    }

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public void register(TbUser user, String code_page) {
//        1、比较验证码
//            1.1 判断是否能从redis中获取到验证码
        String code_redis = redisTemplate.boundValueOps("ly:sms:" + user.getPhone()).get();
        if(StringUtils.isEmpty(code_redis)){
            throw new LyException(ExceptionEnum.TIME_OUT_CODE);
        }
//            1.2 比较redis中的验证码和页面上传过来的
        if(!StringUtils.equals(code_redis,code_page)){
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }
//        2、密码加密
        String password = user.getPassword(); // 明文的密码
//        使用spring框架的加密方式
        password = bCryptPasswordEncoder.encode(password);
        user.setPassword(password);
//        3、插入到用户表中
        boolean save = this.save(user);
        if(!save){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

//        4、把redis中的验证码删除
        redisTemplate.delete("ly:sms:" + user.getPhone());
    }

    @Override
    public UserDTO queryUserByUsernameAndPassword(String username, String password) {  // password明文的
//        先根据用户名查询，如果能查询出数据，然后在比较密码

        QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbUser::getUsername,username);
        TbUser tbUser = this.getOne(queryWrapper);
//        判断是否能查出数据
        if(tbUser==null){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        String password_miwen = tbUser.getPassword();
//        比较密码
        boolean matches = bCryptPasswordEncoder.matches(password, password_miwen);
        if(!matches){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        return BeanHelper.copyProperties(tbUser, UserDTO.class);
    }
}
